package com.ptu.spzx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ptu.spzx.common.exception.ptuException;
import com.ptu.spzx.domain.Class.Classes;
import com.ptu.spzx.domain.Course.Course;
import com.ptu.spzx.domain.Delete.DeleteIds;
import com.ptu.spzx.domain.Exam.Exam;
import com.ptu.spzx.domain.Exam.ExamClass;
import com.ptu.spzx.domain.Exam.ExamExampaper;
import com.ptu.spzx.domain.Exam.Exampaper;
import com.ptu.spzx.domain.Exam.dto.ExamDTO;
import com.ptu.spzx.domain.Exam.vo.*;
import com.ptu.spzx.domain.Stu.StuAnswer;
import com.ptu.spzx.feign.userInfo.UserInfoFeignClient;
import com.ptu.spzx.mapper.*;
import com.ptu.spzx.model.vo.common.ResultCodeEnum;
import com.ptu.spzx.service.IExamClassService;
import com.ptu.spzx.service.IExamExampaperService;
import com.ptu.spzx.service.IExamService;
import com.ptu.spzx.model.entity.user.UserInfo;
import com.ptu.spzx.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author YT
 * @since 2024-01-28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements IExamService {
    private final IExamClassService iExamClassService;
    private final IExamExampaperService iExamExampaperService;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private ClassesMapper classesMapper;

    @Autowired
    private ExamClassMapper examClassMapper;

    @Autowired
    private StuAnswerMapper stuAnswerMapper;

    @Autowired
    private ExamExampaperMapper examExampaperMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ExampaperMapper exampaperMapper;

    //  添加考试
    @Override
    public void addExam(ExamDTO examDTO) {
        if (examDTO.getSemester() == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        Exam exams = new Exam();
        List<ExamClass> stuExams1 = new ArrayList<>();
        List<ExamExampaper> examExamPapers = new ArrayList<>();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date publishTime = df.parse(examDTO.getExamPublishTime());
            Date beginTime = df.parse(examDTO.getExamBeginTime());
            Date endTime = df.parse(examDTO.getExamEndTime());
            if (publishTime.getTime() - beginTime.getTime() > 0) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
            if (beginTime.getTime() - endTime.getTime() > 0) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
        }

        exams.setCourseId(examDTO.getCourseId());
        exams.setExamName(examDTO.getExamName());
        exams.setExamPublishTime(examDTO.getExamPublishTime());
        exams.setExamBeginTime(examDTO.getExamBeginTime());
        exams.setExamEndTime(examDTO.getExamEndTime());
        exams.setExamDescription(examDTO.getExamDescription());
        exams.setSemester(examDTO.getSemester());
        examMapper.insert(exams);
        for (Long classId : examDTO.getClassId()) {
            ExamClass examClass = new ExamClass();
            examClass.setClassId(classId);
            examClass.setExamId(exams.getExamId());
            stuExams1.add(examClass);
        }
        iExamClassService.saveBatch(stuExams1);
        for (Long EpId : examDTO.getExamPaperId()) {
            ExamExampaper examPapers = new ExamExampaper();
            examPapers.setExamId(exams.getExamId());
            examPapers.setEpId(EpId);
            examExamPapers.add(examPapers);
        }
        iExamExampaperService.saveBatch(examExamPapers);
        try {
            if (examDTO.getCourseId() == null) {
                throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
            }
        } catch (Exception e) {
            throw new ptuException(ResultCodeEnum.DATA_ERROR);
        }

    }

    //    删除考试
    @Override
    public void delExamById(DeleteIds deleteIds) {
        List<Long> ids = deleteIds.getIds();
        if (ids == null||ids.size()==0) {
            throw new ptuException(ResultCodeEnum.PARAM_NULL);
        }
        for(Long examId:ids){
            HashMap<String, Object> Mp = new HashMap<>();
            Mp.put("exam_id", examId);
            iExamExampaperService.removeByMap(Mp);
            iExamClassService.removeByMap(Mp);
            removeById(examId);
        }
    }

    //更新考试
    @Override
    public void updateExam(ExamDTO examDTO) {
    if(examDTO.getExamId()==null){
        throw new ptuException(ResultCodeEnum.PARAM_NULL);
    }
    Exam exam = BeanCopyUtils.copyBean(examDTO, Exam.class);
    examMapper.updateById(exam);
    LambdaQueryWrapper<ExamExampaper> lambdaQueryWrapper=new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(ExamExampaper::getExamId,examDTO.getExamId());
    examExampaperMapper.delete(lambdaQueryWrapper);
    for(Long epId:examDTO.getExamPaperId()){
        ExamExampaper examExampaper=new ExamExampaper();
        examExampaper.setExamId(examDTO.getExamId());
        examExampaper.setEpId(epId);
        examExampaperMapper.insert(examExampaper);
    }
    LambdaQueryWrapper<ExamClass> lambdaQueryWrapper2=new LambdaQueryWrapper<>();
    lambdaQueryWrapper2.eq(ExamClass::getExamId,examDTO.getExamId());
    examClassMapper.delete(lambdaQueryWrapper2);
    for(Long classId:examDTO.getClassId()){
        ExamClass examClass=new ExamClass();
        examClass.setClassId(classId);
        examClass.setExamId(examDTO.getExamId());
        examClassMapper.insert(examClass);
    }
    }


    //获取考试详细
    @Override
    public ExamVO getExamDetailById(Long id) {
    if(id==null){
        throw new ptuException(ResultCodeEnum.PARAM_NULL);
    }
    Exam exam = examMapper.selectById(id);
    if(exam==null){
        throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
    }
    ExamVO examVO = BeanCopyUtils.copyBean(exam, ExamVO.class);
    List<Long> classIds=classesMapper.selectByExamId(id);
    examVO.setClassId(classIds);
    List<Long> epIds=examExampaperMapper.selectByExamId(id);
    examVO.setExamPaperId(epIds);
    return examVO;
    }

    @Override
    public PageInfo<Exam> getExamByCourseIdSemester(Integer courseId, String semester,Integer pageNum,Integer pageSize) {
        LambdaQueryWrapper<Exam> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(courseId != null, Exam::getCourseId, courseId)
                .eq(StringUtils.isNotBlank(semester), Exam::getSemester, semester);
        PageHelper.startPage(pageNum,pageSize);
        List<Exam> exams = examMapper.selectList(lambdaQueryWrapper);
        PageInfo<Exam> pageInfo=new PageInfo<>(exams);
        return pageInfo;
    }

    @Override
    public List getStuExam(String stuId) {
        UserInfo stu = userInfoFeignClient.getStu(stuId);
        if (stu == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        String className = stu.getClassName();
        Long classId = classesMapper.seectByName(className);
        LambdaQueryWrapper<ExamClass> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ExamClass::getClassId, classId);
        List<ExamClass> examClasses = examClassMapper.selectList(lambdaQueryWrapper);
        List allExam = new ArrayList();
        for (ExamClass examClass : examClasses) {
            Long examId = examClass.getExamId();
            Exam exam = examMapper.selectById(examId);
            if(exam==null){
                throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
            }
            Integer courseId = exam.getCourseId();
            Course course = courseMapper.selectById(courseId);
            long dd = 1000 * 24 * 60 * 60;//一天的毫秒数
            long hh = 1000 * 60 * 60;//一小时的毫秒数
            long mm = 1000 * 60;//一分钟的毫秒数
            //远程调用课程模块 设置课程名称 预留接口
            String examPublishTime = exam.getExamPublishTime();
            String examBeginTime = exam.getExamBeginTime();
            String examEndTime = exam.getExamEndTime();
            StuExamVo stuExamVo = BeanCopyUtils.copyBean(exam, StuExamVo.class);
            stuExamVo.setStuId(stuId);
            stuExamVo.setCourseName(course.getCourseName());
            long day = 0;
            long hour = 0;
            long min = 0;
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date publishTime = null;
            long current = Calendar.getInstance().getTimeInMillis();
            try {
                publishTime = df.parse(examPublishTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            try {
                if (current - publishTime.getTime() >= 0) {
                    examMapper.selectById(examId);
                    // 2. 时间类型转化
                    Date d1 = df.parse(examEndTime);
                    Date d2 = df.parse(examBeginTime);
                    // 3. 时间计算
                    long diff = d1.getTime() - d2.getTime();// 这样得到的差值是微秒级别
                    // 4. 对结果时间进行转化
                    if (diff / dd > 1) {
                        day = diff / dd;
                        hour = diff % dd / hh;
                        min = diff % dd % hh / mm;
                        String duration = (day) + "天" + hour + "时" + min + "分";
                        stuExamVo.setDuration(duration);
                    } else {
                        min = diff / mm;
                        String duration = min + "分";
                        stuExamVo.setDuration(duration);
                    }
                    if (current - publishTime.getTime() < 0) {
                        stuExamVo.setStatus(0);
                    } else if (current - publishTime.getTime() >= 0 && current - d2.getTime() < 0) {
                        stuExamVo.setStatus(1);
                    } else if (current - d2.getTime() > 0 && current - d1.getTime() < 0) {
                        stuExamVo.setStatus(2);
                    } else {
                        stuExamVo.setStatus(3);
                    }
                    allExam.add(stuExamVo);
                }
            } catch (Exception e) {
                throw new ptuException(ResultCodeEnum.TIME_EXCEPTION);
            }
        }
        return allExam;
    }

    @Override
    public ExamStuVo getStuAnalyse(Long examId, List<Long> classIds) {
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ptuException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        ExamStuVo examStuVo = BeanCopyUtils.copyBean(exam, ExamStuVo.class);
        List<Long> classIdss = examClassMapper.selectByExamId(examId);
        //所有学生的学号
        List<String> stuListByClass = new ArrayList<>();
        if (classIds != null) {
            List<Classes> classes = classesMapper.selectBatchIds(classIds);
            for (Classes classes1 : classes) {
                String name = classes1.getName();
                List<String> stuListByClass1 = userInfoFeignClient.getStuListByClass(name);
                stuListByClass.addAll(stuListByClass1);
            }
        } else {
            List<Classes> classes = classesMapper.selectBatchIds(classIdss);
            for (Classes classes1 : classes) {
                String name = classes1.getName();
                List<String> stuListByClass1 = userInfoFeignClient.getStuListByClass(name);
                stuListByClass.addAll(stuListByClass1);
            }
        }
        //获取提交学生的Id
        List<String> stuIds = new ArrayList<>();
        //获取未提交学生的Id
        List<String> unsubmitStuIds = new ArrayList<>();
        //获取提交学生的成绩
        List<Float> stuIdScore = new ArrayList<>();
        //获取未提交学生的成绩集合
        List<Float> unsubmitStuIdScore= new ArrayList<>();
        LambdaQueryWrapper<StuAnswer> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StuAnswer::getExamId, examId);
        List<StuAnswer> stuAnswers = stuAnswerMapper.selectList(lambdaQueryWrapper);
        for (StuAnswer stuAnswer : stuAnswers) {
            String stuId = stuAnswer.getStuId();
            Integer epStatus = stuAnswer.getEpStatus();
            if (stuListByClass.contains(stuId) && epStatus > 0) {
                stuIds.add(stuId);
                stuIdScore.add(stuAnswer.getStuScore());
            } else {
                unsubmitStuIds.add(stuId);
                unsubmitStuIdScore.add(stuAnswer.getStuScore());
            }
        }
        //获取提交学生的全部信息
        List<UserInfo> stuListByAllStuId = userInfoFeignClient.getStuListByAllStuId(stuIds);
        //获取未提交人数的全部信息
        List<UserInfo> unsubmitStuListByAllStuId = userInfoFeignClient.getStuListByAllStuId(unsubmitStuIds);
        List<UserInfoStuVo> userInfoStuVos = BeanCopyUtils.copyBeanList(stuListByAllStuId, UserInfoStuVo.class);
        List<UserInfoStuVo> unsubmitUserInfoStuVos = BeanCopyUtils.copyBeanList(unsubmitStuListByAllStuId, UserInfoStuVo.class);
        int i=0;
        int j=0;
        for(UserInfoStuVo userInfoStuVo:userInfoStuVos){
        userInfoStuVo.setStuScore(stuIdScore.get(i));
        i+=1;
        }
        System.out.println(userInfoStuVos.size());
        for(UserInfoStuVo unsubmitUserInfoStuVo:unsubmitUserInfoStuVos){
        unsubmitUserInfoStuVo.setStuScore(unsubmitStuIdScore.get(j));
        j+=1;
        }
        examStuVo.setSubmitStu(userInfoStuVos);
        examStuVo.setUnSubmitStu(unsubmitUserInfoStuVos);
        Integer submitSize=userInfoStuVos.size();
        Integer size=userInfoStuVos.size()+unsubmitUserInfoStuVos.size();
        BigDecimal passRate = new BigDecimal((submitSize.doubleValue()/size.doubleValue())*100);
        passRate = passRate.setScale(0, BigDecimal.ROUND_HALF_UP);
        examStuVo.setPassRate(passRate.toString()+"%");
        return examStuVo;
    }

    @Override
    public StuExamScoreVo getStuScoreAnalyse(Long examId, Long classId) {
        Classes classes = classesMapper.selectById(classId);
        //获取试卷
        List<Long> epIds = examExampaperMapper.selectByExamId(examId);
        LambdaQueryWrapper<Exampaper> lambdaQueryWrapperEp=new LambdaQueryWrapper<>();
        lambdaQueryWrapperEp.in(Exampaper::getEpId,epIds);
        List<Exampaper> exampapers = exampaperMapper.selectList(lambdaQueryWrapperEp);
        //获取该班级的学生
        List<String> stuIds = userInfoFeignClient.getStuListByClass(classes.getName());
        List<Float> scores=new ArrayList<>();
        List<StuScoreVo> stuScoreVos=new ArrayList<>();
        for(Exampaper exampaper:exampapers){
            //获取合格分数线
            Float qualifyScore = exampaper.getQualifyScore();
            Float epScore = exampaper.getEpScore();
            Long epId = exampaper.getEpId();
            LambdaQueryWrapper<StuAnswer> lambdaQueryWrapper=new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StuAnswer::getExamId,examId)
                    .in(StuAnswer::getStuId,stuIds)
                    .eq(StuAnswer::getEpId,epId);
            List<StuAnswer> stuAnswers = stuAnswerMapper.selectList(lambdaQueryWrapper);
            for(StuAnswer stuAnswer:stuAnswers){
                Float stuScore = stuAnswer.getStuScore();
                scores.add(stuScore); //获取当前学生的成绩
            }
            //成绩区间划分
            BigDecimal number = new BigDecimal(epScore);
            List<String> epScoreGrade = new ArrayList<>();
            epScoreGrade.add(number.multiply(new BigDecimal("0.0")) + "~" + number.multiply(new BigDecimal("0.2")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.2")) + "~" + number.multiply(new BigDecimal("0.4")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.4")) + "~" + number.multiply(new BigDecimal("0.6")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.6")) + "~" + number.multiply(new BigDecimal("0.8")));
            epScoreGrade.add(number.multiply(new BigDecimal("0.8")) + "~" + number.multiply(new BigDecimal("1.0")));
            //成绩区间人数
            List<Integer> stuScoreGrade = new ArrayList<>();
            int a = 0, b = 0, c = 0, d = 0, f = 0;
            //计算班级考试平均分
            float allScore = 0;
            for(Float score:scores){
                allScore += score;
                if (score >= epScore*0.0 && score <= epScore*0.2) {
                    a++;
                } else if (score > epScore*0.2 && score <= epScore*0.4) {
                    b++;
                } else if (score > epScore*0.4 && score <= epScore*0.6) {
                    c++;
                } else if (score > epScore*0.6 && score <= epScore*0.8) {
                    d++;
                } else {
                    f++;
                }
            }
            stuScoreGrade.add(a);
            stuScoreGrade.add(b);
            stuScoreGrade.add(c);
            stuScoreGrade.add(d);
            stuScoreGrade.add(f);
            BigDecimal avgStuScoreCount = new BigDecimal(allScore / scores.size());
            avgStuScoreCount = avgStuScoreCount.setScale(2, BigDecimal.ROUND_HALF_UP);
            //计算通过人数
            Integer passCount = c + d + f;
            Integer allCount = a + b + c + d + f;
            BigDecimal passRate = new BigDecimal((passCount / allCount)*100);
            //小数点精度为2
            passRate = passRate.setScale(0, BigDecimal.ROUND_HALF_UP);
            StuScoreVo stuScoreVo=new StuScoreVo();
            stuScoreVo.setEpId(epId);
            stuScoreVo.setScoreList(epScoreGrade);
            stuScoreVo.setNumList(stuScoreGrade);
            stuScoreVo.setAverageScore(avgStuScoreCount);
            stuScoreVo.setPassRate(passRate);
            stuScoreVos.add(stuScoreVo);
        }
        StuExamScoreVo stuExamScoreVo=new StuExamScoreVo();
        stuExamScoreVo.setExamId(examId);
        stuExamScoreVo.setExamId(examId);
        stuExamScoreVo.setExamPaperScore(stuScoreVos);
        return stuExamScoreVo;
    }

    @Override
    public PageInfo<UserInfo> getExamStuNum(Long examId, Integer pageNum, Integer pageSize) {
        List<Long> classIds = examClassMapper.selectByExamId(examId);
        List<String> classNames=new ArrayList<>();
        for(Long classId:classIds){
            List<String> className=classesMapper.selectNameByClassId(classId);
            classNames.addAll(className);
        }
        PageInfo<UserInfo> stuListByClassName = userInfoFeignClient.getStuListByClassName(classNames, pageNum, pageSize);
        return stuListByClassName;
    }
}
